package rpc.netcon.jetty.server;

import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cglib.reflect.FastClass;
import org.springframework.cglib.reflect.FastMethod;
import rpc.netcon.ReturnT;
import rpc.netcon.RpcRequest;
import rpc.netcon.RpcResponse;

/**
 * Created by zhangyanfei on 2018/10/11.
 *
 * @author zhangyanfei
 * @date 2018/10/11
 */
public class NetComServerFactory {

    private static final Logger logger = LoggerFactory.getLogger(NetComServerFactory.class);

    private static Map<String, Object> serviceMap = new HashMap<>();
    private static String accessToken;

    public static void putService(Class<?> iface, Object serviceBean) {
        serviceMap.put(iface.getName(), serviceBean);
    }

    public static void setAccessToken(String accessToken) {
        NetComServerFactory.accessToken = accessToken;
    }

    JettyServer server = new JettyServer();

    // 每个服务带一个 jetty server 用来和job-admin 通信
    public void start(int port, String ip, String appName) throws Exception {
        server.start(port, ip, appName);
    }

    public void destory() {
        server.distory();
    }

    public static RpcResponse invokeService(RpcRequest request, Object serviceBean) {
        if (serviceBean == null) {
            serviceBean = serviceMap.get(request.getClassName());
        }
        if (serviceBean == null) {
            //todo
        }
        RpcResponse response = new RpcResponse();
        // 时间搓校验
        if (Math.abs(System.currentTimeMillis() - request.getCreateMillisTime()) > 180000) {
            // 服务端和客户端的时间相差3min钟
            response.setResult(new ReturnT<String>(ReturnT.FAIL_CODE,
                "The timestamp difference between admin and executor exceeds the limit."));
            return response;
        }

        // token 校验
        if (accessToken != null && accessToken.trim().length() > 0 && !accessToken.trim().equals(
            request.getAccessToken())) {
            response.setResult(
                new ReturnT<String>(ReturnT.FAIL_CODE, "The access token[" + request.getAccessToken() + "] is wrong."));
            return response;
        }

        // 触发远程调用的方法
        try {
            //1.获取服务类
            Class<?> serviceClass = serviceBean.getClass();
            //2.获取请求的方法
            String methodName = request.getMethodName();
            //3.获取请求参数类型
            Class<?>[] parameterTypes = request.getParameterTypes();
            //4.获取请求参数
            Object[] parameters = request.getParameters();
            //cglib 创建代理类
            FastClass serviceFastClass = FastClass.create(serviceClass);
            // 创建代理方法
            FastMethod serviceFastMethod = serviceFastClass.getMethod(methodName, parameterTypes);
            // 执行
            Object result = serviceFastMethod.invoke(serviceBean, parameters);
            response.setResult(result);
        } catch (Throwable t) {
            t.printStackTrace();
            response.setError(t.getMessage());
        }
        return response;
    }
}
